import chardet
import os
import pandas as pd
import traceback

class ktbo_excel_reader_engineer(object):
    def __init__(self,excel_file,auto_separator=True,separator='\t'):
        self.excel_file = None
        self.separator = None
        self.auto_separator = None
        self.separators = {
            '\t': 0,  # 制表符
            ',': 0,  # 逗号
            ';': 0,  # 分号
            '|': 0,  # 竖线
            ' ': 0  # 空格
        }
        self.encodings = {
            'gbk', 'gb2312', 'utf-8-sig', 'latin1', 'iso-8859-1'
        }
        self.settings(excel_file,auto_separator=auto_separator,separator=separator)

    def settings(self,excel_file,auto_separator=True,separator='\t'):
        self.excel_file=excel_file
        self.separator=separator
        self.auto_separator=auto_separator

    def process_excel(self):
        return self.analyze_and_load(self.excel_file,self.auto_separator,self.separator)

    def getPandasObject(self):
        return self.process_excel()['split_df']

    def add_separators(self,separators):
        self.separators.add(separators)

    def add_encodings(self,encodings):
        self.encodings.add(encodings)

    def analyze_and_load(self,file_path,auto_separator,separators='\t'):
        global split_df
        analysis_results = self.analyze_file(file_path)
        detected_encoding = analysis_results['encoding_guess']['encoding'] or 'gbk'
        confidence = analysis_results['encoding_guess']['confidence']
        self.encodings.add(detected_encoding)
        unique_encodings = []
        [unique_encodings.append(e) for e in self.encodings if e not in unique_encodings]
        lines = None
        for encoding in unique_encodings:
            try:
                with open(file_path, 'r', encoding=encoding) as f:

                    lines = [line.strip() for line in f.readlines()]

                    break
            except Exception as e:
                print(f"× 编码 '{encoding}' 失败: {str(e)}")
                continue
        if lines is None:
            raise ValueError(f"无法使用任何编码读取文件: {file_path}")
        text_df = pd.DataFrame(lines, columns=['raw_content'])
        text_df['line_num'] = text_df.index + 1
        text_df['char_count'] = text_df['raw_content'].apply(len)
        structured_df = pd.DataFrame()
        try:
            if auto_separator:
                sep = self.auto_detect_separator(lines)
            else:
                sep = self.separator
            split_df = text_df['raw_content'].str.split(sep, expand=True)
            num_cols = split_df.shape[1]
            split_df.columns = [f'col_{i}' for i in range(num_cols)]


            structured_df = pd.concat([text_df, split_df], axis=1)

        except Exception as e:
            print(f"创建结构化DataFrame失败: {e}")
            structured_df = text_df

        return {
            'analysis': analysis_results,  # 文件分析结果
            'text_df': text_df,  # 包含原始文本的DataFrame
            'structured_df': structured_df,  # 包含分割列的结构化DataFrame
            'lines': lines,  # 原始行列表（用于快速访问）
            'split_df': split_df
        }

    def analyze_file(self,file_path):
        results = {}
        results['file_size'] = os.path.getsize(file_path)
        results['file_extension'] = os.path.splitext(file_path)[1].lower()


        with open(file_path, 'rb') as f:

            raw_data = f.read(5000)


        encoding_result = chardet.detect(raw_data)
        results['encoding_guess'] = encoding_result

        header = raw_data[:8]
        results['file_header'] = header
        try:
            decoded_content = raw_data.decode('utf-8')
            results['is_valid_utf8'] = True
        except UnicodeDecodeError as e:
            results['is_valid_utf8'] = False
            results['utf8_error'] = str(e)

        return results

    def auto_detect_separator(self,lines, sample_size=50):
        sample_lines = lines[:min(sample_size, len(lines))]
        for sep in self.separators.keys():
            total = 0
            for line in sample_lines:
                if len(line) > 10:
                    total += line.count(sep)
            self.separators[sep] = total / len(sample_lines)
        best_sep = max(self.separators, key=self.separators.get)
        best_score = self.separators[best_sep]
        if best_score < 1.5:
            return None
        return best_sep

if '__main__' == __name__:#测试
    ktbo = ktbo_excel_reader_engineer('As-50_AlleleReport.xls',auto_separator=True)
    kp=ktbo.getPandasObject()
    print(kp.iloc[0:20,0:2])

